package com.zxq.ruoyi.network.tcp.handler.dispatch;

import com.zxq.frame.core.ExchangeDTO;
import com.zxq.ruoyi.domain.IotDevice;
import com.zxq.ruoyi.facade.DBFacade;
import com.zxq.ruoyi.network.tcp.cache.TcpChannelCache;
import com.zxq.ruoyi.network.tcp.notify.DeviceStateNotify;
import com.zxq.ruoyi.rabbitmq.RabbitPublishHelper;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.xmlbeans.impl.util.HexBin;

@Slf4j
public abstract class TCPDispatchHandler implements ITcpDispatchHandler {

    public TCPDispatchHandler next = null;


    protected ByteBuf in;
    protected ChannelHandlerContext channel;
    public void injectByteBuf(ChannelHandlerContext channel,ByteBuf in) {
        this.in = in;
        this.channel = channel;
    }

    public final void handlerFrame() {
        if(isThisFrame()) {
            log.info(String.format("dev:%s handler:%s",TcpChannelCache.getDevId(channel),getClass().getSimpleName()));
            in.resetReaderIndex();
            decodeFrame();
            in.markReaderIndex();
        } else if(next != null) {
            in.resetReaderIndex();
            log.info(String.format("next:%s handle",getClass().getSimpleName()));
            next.handlerFrame();
        } else {
            in.resetReaderIndex();
            log.info("not find handler");
        }

    }

    @Override
    public void decodeFrame() {
        byte[] frame = trimFrame();
        if(frame == null) {
            log.info("frame is empty");
            return;
        }
        String devId =  TcpChannelCache.getDevId(channel);
        Boolean isRegister = isRegisterFrame();
        log.info("type: " + getClass().getSimpleName() + " frame:" + HexBin.bytesToString(frame));
        if(StringUtils.isEmpty(devId)){
            if(isRegister) {
                devId = inflateDevId(frame);
                IotDevice iotDevice = findDevice(devId);
                if(iotDevice == null) {
                    log.info(String.format("devId:%s not input system!",devId));
                    return;
                }
                DeviceStateNotify.getInstance().online(devId);
                TcpChannelCache.putNettyChannel(devId,channel);
                log.info(String.format("devId:%s load!",devId));
            }
        } else {
            IotDevice iotDevice = findDevice(devId);
            if(iotDevice == null) {
                log.info(String.format("devId:%s loss!",devId));
                return;
            }
            log.info(String.format("type %s is register:%s", devId, isRegister));
            if(isRegister) {
                log.info(String.format("devId:%s already register!",devId));
            }else {
                ExchangeDTO exchangeDTO = new ExchangeDTO();
                exchangeDTO.setData(frame);
                exchangeDTO.setDevId(devId);
                exchangeDTO.setFrameId(iotDevice.getFrameId());
                RabbitPublishHelper.getInstance().devicePublishToMicroService(exchangeDTO);
            }

        }
    }


    /**
     * 解析设备id
     * @param frame
     * @return
     */
    protected String inflateDevId(byte[] frame) {

        return null;
    }


    protected abstract Boolean isRegisterFrame();
    /**
     * 找到对应的设备
     * @param devId 设备id
     * @return
     */
    protected IotDevice findDevice(String devId) {
        IotDevice iotDevice = DBFacade.getInstance().iotDeviceService.selectIotDeviceByDevNum(devId);
        return iotDevice;
    }


    /**
     * 截获一帧长度
     * @return
     */
    protected abstract byte[] trimFrame();





}
